/*
 * Copyright (c) MengChang Wang <wangmengchang@gmail.com>
 * Webpage:  http://www.journalhome.com/texpen/
 *
 *
*/

#include "headers/mainwindow.h"
#include <QTreeWidgetItem>
#include <QAction>
#include <QTextDocument>
#include <QTextCursor>
#include <QVector>
#include <QDebug>

inline QString TextInBrace(QString& doc, int pos, QChar begin='{', QChar end='}'){
    QString title = "";
    if(pos<0){pos=0;}
    int MC = doc.length()-pos;
    int bracecount = 0;
    int mc=0;
    int start=-1;
    int length =-1;
    bool inbrace = false;
    for(;mc<MC;mc++){
        QChar ch = doc.at(pos+mc);
        title += ch;
        if(ch == begin){
            bracecount ++;
            inbrace=true;
            if(start<0){
                start = mc;
            }
        }
        if(ch == end){            
            bracecount --;
        }
        if(bracecount ==0 && inbrace){
            if(start>=0){
                length = mc-start;
            }
            break;
        }
    }
    if(length>2){
        title = title.mid (start+1, length-1);
    }
    return title;
}

bool isTexComment(QString& blk){
    if(!blk.contains("\%")){
        return false;
    }
    int s=0;
    int idx = blk.indexOf("\%",s);
    while(idx>=0){
        if(idx==0 || blk.at(idx-1)!='\\'){
            return true;
        }
        s=idx+1;
        idx = blk.indexOf("\%",s);
    }
    return false;
}

bool isTexComment(QTextCursor& tc){
    QString bc = tc.block().text().mid(0,tc.positionInBlock());
    return(isTexComment(bc));
}

bool isTexComment(QString& ct, int pos){
    if(pos<0 || ct.isEmpty()){
        return false;
    }
    int idx = ct.indexOf("\n");
    if(idx>pos || idx<0){
        //only one line in ct
        QString md = ct.mid(0,pos);
        return isTexComment(md);
    }else{
        int np = idx;
        while(idx<pos){
            np = idx;
            idx=ct.indexOf("\n",idx+1);
        }
        QString md = ct.mid(np+1,pos-np);
        return isTexComment(md);
    }
    return false;
}


bool isProcessing = false;

void MainWindow::reloadTree(){
    if(!isProcessing){
        return;
    }
    structure->clear();
    structure->setHeaderHidden(true);
    structure->insertTopLevelItems(0, ItemList);
    structure->expandAll();
    if(ItemList.isEmpty()){
        if(Settings.OutlineVisible){
            outline->hide();
        }
    }else{
        ApplySettings();
    }
    isProcessing = false;
}

void MainWindow::reloadStructure(){
    //for LaTeX : Charter / Section/ Subsection/ Subsubsection
    if(isProcessing){
        //Do not try to reload when reloading
        return;
    }

    isProcessing = true;

    int curFindPos = 0;

    ItemList.clear();
    QVector<int> Levels;
    Levels.clear();

    QString cnt = TextEdit->toPlainText();//uncouple them
    int chapPos =-1;
    int secPos =-1;
    int subsecPos = -1;
    int subsubPos = -1;
    chapPos =cnt.indexOf("\\chapter{",curFindPos);
    while(chapPos>=0 && isTexComment(cnt,chapPos)){
        chapPos = cnt.indexOf("\\chapter{", chapPos +1);
    }
    secPos =cnt.indexOf("\\section{",curFindPos);
    while(secPos>=0 && isTexComment(cnt,secPos)){
        secPos = cnt.indexOf("\\section{",secPos+1);
    }
    subsecPos =cnt.indexOf("\\subsection{",curFindPos);
    while(subsecPos>=0 && isTexComment(cnt,subsecPos)){
        subsecPos = cnt.indexOf("\\subsection{",subsecPos+1);
    }
    subsubPos =cnt.indexOf("\\subsubsection{",curFindPos);
    while(subsubPos>=0 && isTexComment(cnt,subsubPos)){
        subsubPos = cnt.indexOf("\\subsubsection{",subsubPos+1);
    }

    //first appreance of each category
    //now process
    while(chapPos >=0 || secPos >=0 || subsecPos>=0 || subsubPos>=0){
        int Level=-1;//chapter :0; section: 1; subsection: 2; subsubsection: 3;
        int minpos = -1;
        if(chapPos>=0 && (chapPos<minpos || minpos<0) ){
            minpos = chapPos;
            Level =0;
        }
        if(secPos>=0 && (secPos<minpos || minpos<0) ){
            minpos = secPos;
            Level =1;
        }
        if(subsecPos>=0 && (subsecPos<minpos || minpos<0) ){
            minpos = subsecPos;
            Level =2;
        }
        if(subsubPos>=0 && (subsubPos<minpos || minpos<0) ){
            minpos = subsubPos;
            Level =3;
        }
        if(curFindPos < minpos){
            curFindPos = minpos;
        }

        QTreeWidgetItem* aItem=NULL;
        aItem = new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("%1").arg(TextInBrace(cnt,curFindPos-1))));
        aItem->setData(0,Qt::UserRole,curFindPos);
        ItemList.append(aItem);
        Levels.push_back(Level);

        curFindPos += 1;

        chapPos =cnt.indexOf("\\chapter{",curFindPos);
        while(chapPos>=0 && isTexComment(cnt,chapPos)){
            chapPos = cnt.indexOf("\\chapter{", chapPos +1);
        }
        secPos =cnt.indexOf("\\section{",curFindPos);
        while(secPos>=0 && isTexComment(cnt,secPos)){
            secPos = cnt.indexOf("\\section{",secPos+1);
        }
        subsecPos =cnt.indexOf("\\subsection{",curFindPos);
        while(subsecPos>=0 && isTexComment(cnt,subsecPos)){
            subsecPos = cnt.indexOf("\\subsection{",subsecPos+1);
        }
        subsubPos =cnt.indexOf("\\subsubsection{",curFindPos);
        while(subsubPos>=0 && isTexComment(cnt,subsubPos)){
            subsubPos = cnt.indexOf("\\subsubsection{",subsubPos+1);
        }
    }

    for(int i=1;i<Levels.size();i++){
        if(Levels.at(i)>0){
            int p = -1;
            for(int j=i;j>=0;j--){
                if(Levels.at(j) < Levels.at(i)){
                    p = j;
                    break;
                }
            }
            if(p >= 0){
                ItemList.at(p)->addChild(ItemList.at(i));
            }
        }
    }

    emit(nowRefreshStructure());

    return;
}

void MainWindow::jumpToTag(QTreeWidgetItem* item, int col){
    Q_UNUSED(col);

    if(item==NULL){
        return;
    }
    int pos = item->data(0,Qt::UserRole).toInt();
    QTextCursor crs(TextEdit->document());
    crs.setPosition(pos);
    TextEdit->setTextCursor(crs);
    TextEdit->centerCursor ();
    TextEdit->setFocus();
}

